package com.ihg.hiex.admin.web.controller.session.after;

import java.util.List;
import java.util.Map;

import org.apache.commons.collections.MapUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;

import com.demo2do.core.entity.result.HttpResult;
import com.demo2do.core.utils.CollectionUtils;
import com.demo2do.core.web.interceptor.MenuSetting;
import com.demo2do.core.web.resolver.Preloading;
import com.ihg.hiex.admin.entity.search.CoachingProgressSearch;
import com.ihg.hiex.admin.entity.security.Login;
import com.ihg.hiex.admin.service.account.DelegateService;
import com.ihg.hiex.admin.service.session.DelegateCoachingConversationService;
import com.ihg.hiex.admin.service.session.SessionParticipatorService;
import com.ihg.hiex.admin.service.session.SessionReportService;
import com.ihg.hiex.admin.service.session.SessionService;
import com.ihg.hiex.admin.web.resolver.Secure;
import com.ihg.hiex.entity.session.Session;
import com.ihg.hiex.entity.session.after.SessionReport;
import com.ihg.hiex.entity.session.participator.SessionParticipator;
import com.ihg.hiex.entity.user.Administrator;
import com.ihg.hiex.entity.user.Delegate;
import com.ihg.hiex.entity.user.DelegateAttribute;
import com.ihg.hiex.entity.user.DelegateCoachingConversation;

/**
 * 
 * @author dan
 *
 */
@Controller
@RequestMapping("/sessions/{sessionId}/admin-coaching-progress")
@MenuSetting("menu-sessions")
public class AdminCoachingProgressController {
    
    @Autowired
    private SessionService sessionService;
    
    @Autowired
    private SessionParticipatorService sessionParticipatorService;
    
    @Autowired
    private DelegateService delegateService;
    
    @Autowired
    private DelegateCoachingConversationService delegateCoachingConversationService;
    
    @Autowired
    private SessionReportService sessionReportService;
    
    private static final Logger logger = LoggerFactory.getLogger(AdminCoachingProgressController.class);
    
    
    
    /**
     * 
     * @param sessionId
     * @return
     */
    @SuppressWarnings("unchecked")
    @MenuSetting("submenu-session-admin-after-coach-progress")
    @RequestMapping(path = "", method=RequestMethod.GET)
    public ModelAndView index(@PathVariable("sessionId") Long sessionId) {
        ModelAndView modelAndView = new ModelAndView("session/admin-coaching-progress/coaching-progress-list");
        
        Session session = sessionService.load(sessionId);
        modelAndView.addObject("session", session);
        
        List<SessionParticipator> participators = sessionParticipatorService.list(session);
        List<Long> delegateIds = CollectionUtils.extractPropertyList(participators, "delegateId");
        List<Delegate> delegates = delegateService.list(delegateIds);
        modelAndView.addObject("delegates", delegates);
        
        // list delegate coaching conversation
        Map<String, List<DelegateCoachingConversation>> conversations = delegateCoachingConversationService.listConversation(session);
        modelAndView.addObject("conversations", conversations);
        
        // get delegate's finish conversation and total conversation
        Map<String, Map<String, Integer>> conversationAmount = delegateCoachingConversationService.generateConversationAmount(conversations);
        modelAndView.addObject("conversationAmount", conversationAmount);
        
        // get delegate coach
        Map<String, Map<String, DelegateAttribute>> attributes = delegateService.listAttribute(delegates);
        modelAndView.addObject("attributes", attributes);
        
//        Map<String, SessionReport> sessionReports = sessionReportService.list(session);
//        modelAndView.addObject("sessionReports", sessionReports);
        
        return modelAndView;
    }
    
    /**
     * 
     * @param sessionId
     * @return
     */
    @RequestMapping(value = "/search", method = RequestMethod.GET)
    public ModelAndView search(@PathVariable("sessionId") Long sessionId) {
        ModelAndView modelAndView = new ModelAndView("session/admin-coaching-progress/coaching-progress-search");
        
        modelAndView.addObject("sessionId", sessionId);
        
        return modelAndView;
    }

    /**
     * 
     * @param search
     * @param sessionId
     * @return
     */
    @RequestMapping(value = "", method = RequestMethod.GET, params = "filter")
    @MenuSetting("submenu-session-admin-after-coach-progress")
    public ModelAndView onSearch(CoachingProgressSearch search,@PathVariable("sessionId") Long sessionId) {
        
        ModelAndView modelAndView = new ModelAndView("session/admin-coaching-progress/coaching-progress-list");
        
        Session session = sessionService.load(sessionId);
        modelAndView.addObject("session", session);
        
        List<Delegate> delegates = delegateService.search(search);
        modelAndView.addObject("delegates", delegates);
        
        // list delegate coaching conversation
        Map<String, List<DelegateCoachingConversation>> conversations = delegateCoachingConversationService.listConversation(session);
        modelAndView.addObject("conversations", conversations);
        
        // get delegate's finish conversation and total conversation
        Map<String, Map<String, Integer>> conversationAmount = delegateCoachingConversationService.generateConversationAmount(conversations);
        modelAndView.addObject("conversationAmount", conversationAmount);
        
        // get delegate coach
        Map<String, Map<String, DelegateAttribute>> attributes = delegateService.listAttribute(delegates);
        modelAndView.addObject("attributes", attributes);
        
        return modelAndView;
        
    }
    
    /**
     * 
     * @param sessionId
     * @param delegateId
     * @return
     */
    @MenuSetting("submenu-session-admin-after-coach-progress")
    @RequestMapping(path = "/delegates/{delegateId}", method=RequestMethod.GET)
    public ModelAndView view(@PathVariable("sessionId") Long sessionId,
                             @PathVariable("delegateId") Long delegateId) {
        ModelAndView modelAndView = new ModelAndView("session/admin-coaching-progress/coaching-progress-view");
        
        Delegate delegate = delegateService.load(Delegate.class, delegateId);
        modelAndView.addObject("delegate", delegate);
        
        // list delegate attribute
        Map<String, DelegateAttribute> delegateAttributes = delegateService.listAttribute(delegate);
        modelAndView.addObject("delegateAttributes", delegateAttributes);
        
        List<DelegateCoachingConversation> conversations = delegateCoachingConversationService.list(delegate);
        modelAndView.addObject("conversations", conversations);
        
        Session session = sessionService.load(sessionId);
        modelAndView.addObject("session", session);
        
        // load session report
        SessionReport sessionReport = sessionReportService.load(session, delegate);
        modelAndView.addObject("sessionReport", sessionReport);
        
        return modelAndView;
    }
    
    /**
     * 
     * @param sessionId
     * @param delegateId
     * @return
     */
    @RequestMapping(value = "/delegates/{delegateId}/bind-exist-coach" , method = RequestMethod.GET)
    public ModelAndView bindExistCoach(@PathVariable("sessionId") Long sessionId, @PathVariable("delegateId") Long delegateId) {
        
        ModelAndView modelAndView = new ModelAndView("session/admin-coaching-progress/coaching-progress-bind-exist-coach");
        
        modelAndView.addObject("sessionId", sessionId);
        modelAndView.addObject("delegateId", delegateId);
        
        Delegate delegate = delegateService.load(Delegate.class, delegateId);
        Map<String, DelegateAttribute> delegateAttributes = delegateService.listAttribute(delegate);
        modelAndView.addObject("delegateCoach", MapUtils.isNotEmpty(delegateAttributes) ? delegateAttributes.get("delegate-coach") : null);
        
        return modelAndView;
        
    }
    
    /**
     * 
     * @param login
     * @param delegateId
     * @param coach
     * @return
     */
    @RequestMapping(value = "/delegates/{delegateId}/bind-exist-coach" , method = RequestMethod.PATCH, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public @ResponseBody HttpResult onBindExistCoach(@Secure Login login,
                                                     @PathVariable("sessionId") Long sessionId,
                                                     @PathVariable("delegateId") Long delegateId,
                                                     @RequestParam("coach") Long coach) {
        
        HttpResult httpResult = new HttpResult();
        
        try {
            
            Delegate delegate = delegateService.load(Delegate.class, delegateId);
            Map<String, DelegateAttribute> delegateAttributes = delegateService.listAttribute(delegate);
            Session session = sessionService.load(Session.class, sessionId);
            
            if(MapUtils.isNotEmpty(delegateAttributes) && delegateAttributes.get("delegate-coach") != null) {
                delegateService.editDelegateAttribute(delegateAttributes.get("delegate-coach"), coach.toString(), session);
            } else {
                delegateService.addDelegateAttribute(delegate, "delegate-coach", coach.toString(), session);
            }
             
            httpResult.success().message("Successed");
            
        } catch (Exception e) {
            httpResult.fail("500").message("Failed");
            logger.error("#onBindExistCoach() - bindExistCoach fail, exception is [{}]",e);
        }
        
        return httpResult;
        
    }
    
    /**
     * 
     * @param sessionId
     * @param delegateId
     * @return
     */
    @RequestMapping(value = "/delegates/{delegateId}/bind-new-coach" , method = RequestMethod.GET)
    public ModelAndView bindNewCoach(@PathVariable("sessionId") Long sessionId, @PathVariable("delegateId") Long delegateId) {
        
        ModelAndView modelAndView = new ModelAndView("session/admin-coaching-progress/coaching-progress-bind-new-coach");
        
        modelAndView.addObject("sessionId", sessionId);
        modelAndView.addObject("delegateId", delegateId);
        
        return modelAndView;
        
    }
    
    /**
     * 
     * @param login
     * @param delegateId
     * @param admin
     * @return
     */
    @RequestMapping(value = "/delegates/{delegateId}/bind-new-coach" , method = RequestMethod.PATCH, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public @ResponseBody HttpResult onBindNewCoach(@Secure Login login,
                                                   @PathVariable("sessionId") Long sessionId,             
                                                   @PathVariable("delegateId") Long delegateId,
                                                   Administrator admin) {
        
        HttpResult httpResult = new HttpResult();
        
        try {
            
            Session session = sessionService.load(Session.class, sessionId);
            Delegate delegate = delegateService.load(Delegate.class, delegateId);
            delegateService.bindCoach(admin, delegate, session);
             
            httpResult.success().message("Successed");
            
        } catch (Exception e) {
            httpResult.fail("500").message("Failed");
            logger.error("#onBindNewCoach() - bindNewCoach fail, exception is [{}]",e);
        }
        
        return httpResult;
        
    }
    
    /**
     * 
     * @param sessionId
     * @param conversationId
     * @return
     */
    @RequestMapping(value = "/coaching-conversations/{conversationId}/confirm" , method = RequestMethod.GET)
    public ModelAndView confirm(@PathVariable("sessionId") Long sessionId, @PathVariable("conversationId") Long conversationId) {
        
        ModelAndView modelAndView = new ModelAndView("session/after/coaching-conversation-submit");
        
        modelAndView.addObject("sessionId", sessionId);
        modelAndView.addObject("conversationId", conversationId);
        
        return modelAndView;
        
    }
    
    /**
     * 
     * @param login
     * @param conversation
     * @return
     */
    @RequestMapping(value = "/coaching-conversations/{conversationId}/confirm" , method = RequestMethod.PATCH, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public @ResponseBody HttpResult onConfirm(@Secure Login login, @Preloading("conversationId") DelegateCoachingConversation conversation) {
        
        HttpResult httpResult = new HttpResult();
        
        try {
            
            
            httpResult.success().message("Successed");
            
        } catch (Exception e) {
            httpResult.fail("500").message("Failed");
            logger.error("#onConfirm() - delete fail, exception is [{}]",e);
        }
        
        return httpResult;
        
    }

}
